package com.example.springbootflowabledemo.controller;

import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/***
 * 查看流程图的实时执行情况，这样方便我们查看流程到底执行到哪一步了
 */

@Slf4j
@RestController
@RequestMapping("/flow-demo")
public class HelloController {

	String zuzhangId = "12";
	String managerId = "80";

	@Autowired
	RuntimeService runtimeService;

	@Autowired
	TaskService taskService;

	@Autowired
	RepositoryService repositoryService;

	@Autowired
	ProcessEngine processEngine;

	@GetMapping("/pic")
	public void showPic(HttpServletResponse resp, String processId) throws Exception {
		ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
		if (pi == null) {
			return;
		}
		List<Execution> executions = runtimeService
				.createExecutionQuery()
				.processInstanceId(processId)
				.list();

		List<String> activityIds = new ArrayList<>();
		List<String> flows = new ArrayList<>();
		for (Execution exe : executions) {
			List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
			activityIds.addAll(ids);
		}

		/**
		 * 生成流程图
		 */
		BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
		ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
		ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
		InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0, false);
		OutputStream out = null;
		byte[] buf = new byte[1024];
		int legth = 0;
		try {
			out = resp.getOutputStream();
			while ((legth = in.read(buf)) != -1) {
				out.write(buf, 0, legth);
			}
		} finally {
			if (in != null) {
				in.close();
			}
			if (out != null) {
				out.close();
			}
		}
	}


	/**
	 * 开启一个流程
	 */
	@GetMapping("/askForLeave")
	public void askForLeave() {
		String staffId = "33";
		HashMap<String, Object> map = new HashMap<>();
		map.put("leaveTask", staffId);
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("ask_for_leave", map);
		runtimeService.setVariable(processInstance.getId(), "name", "javaboy");
		runtimeService.setVariable(processInstance.getId(), "reason", "休息一下");
		runtimeService.setVariable(processInstance.getId(), "days", 10);
		log.info("创建请假流程 processId：{}", processInstance.getId());
	}

	/**
	 * 提交给组长审批
	 */
	@GetMapping("/submitToZuzhang")
	public void submitToZuzhang() {
		String staffId = "12";
		//员工查找到自己的任务，然后提交给组长审批
		List<Task> list = taskService.createTaskQuery().taskAssignee(staffId).orderByTaskId().desc().list();
		for (Task task : list) {
			log.info("任务 ID：{}；任务处理人：{}；任务是否挂起：{}", task.getId(), task.getAssignee(), task.isSuspended());
			Map<String, Object> map = new HashMap<>();
			//提交给组长的时候，需要指定组长的 id
			map.put("zuzhangTask", zuzhangId);
			taskService.complete(task.getId(), map);
		}
	}

	/**
	 * 组长审批-批准
	 */
	@GetMapping("/zuZhangApprove")
	public void zuZhangApprove() {
		List<Task> list = taskService.createTaskQuery().taskAssignee(zuzhangId).orderByTaskId().desc().list();
		for (Task task : list) {
			log.info("组长 {} 在审批 {} 任务", task.getAssignee(), task.getId());
			Map<String, Object> map = new HashMap<>();
			//组长审批的时候，如果是同意，需要指定经理的 id
			map.put("managerTask", managerId);
			map.put("checkResult", "通过");
			taskService.complete(task.getId(), map);
		}
	}

	/**
	 * 组长审批-拒绝
	 */
	@GetMapping("/zuZhangReject")
	public void zuZhangReject() {
		List<Task> list = taskService.createTaskQuery().taskAssignee(zuzhangId).orderByTaskId().desc().list();
		for (Task task : list) {
			log.info("组长 {} 在审批 {} 任务", task.getAssignee(), task.getId());
			Map<String, Object> map = new HashMap<>();
			//组长审批的时候，如果是拒绝，就不需要指定经理的 id
			map.put("checkResult", "拒绝");
			taskService.complete(task.getId(), map);
		}
	}

	/**
	 * 经理审批自己的任务-批准
	 */
	@GetMapping("/managerApprove")
	public void managerApprove() {
		List<Task> list = taskService.createTaskQuery().taskAssignee(managerId).orderByTaskId().desc().list();
		for (Task task : list) {
			log.info("经理 {} 在审批 {} 任务", task.getAssignee(), task.getId());
			Map<String, Object> map = new HashMap<>();
			map.put("checkResult", "通过");
			taskService.complete(task.getId(), map);
		}
	}

	/**
	 * 经理审批自己的任务-拒绝
	 */
	@Test
	public void managerReject() {
		List<Task> list = taskService.createTaskQuery().taskAssignee(managerId).orderByTaskId().desc().list();
		for (Task task : list) {
			log.info("经理 {} 在审批 {} 任务", task.getAssignee(), task.getId());
			Map<String, Object> map = new HashMap<>();
			map.put("checkResult", "拒绝");
			taskService.complete(task.getId(), map);
		}
	}

	public class AskForLeaveFail implements JavaDelegate {
		@Override
		public void execute(DelegateExecution execution) {
			System.out.println("请假失败。。。");
		}
	}
}
